package com.game.net.server.jpbsocket;

import com.game.net.BaseServer;
import com.game.message.jpb.codec.JPbDecoder;
import com.game.message.jpb.codec.JPbEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class JPbSocketNettyServer extends BaseServer {
	private Logger logger = LoggerFactory.getLogger(JPbSocketNettyServer.class);
	private int port;

	public void init(int port, final SimpleChannelInboundHandler handler) {
		this.port = port;
		logger.info("start server");
		// 这个是用于serversocketchannel的eventloop,默认线程数是cpu核数*2
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		// 这个是用于处理accept到的channel
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap b = new ServerBootstrap();
			b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
					.childOption(ChannelOption.ALLOCATOR,
							PooledByteBufAllocator.DEFAULT);
			// 设置时间循环对象，前者用来处理accept事件，后者用于处理已经建立的连接的io
			b.group(bossGroup, workerGroup);
			// 用它来建立新accept的连接，用于构造serversocketchannel的工厂类
			b.channel(NioServerSocketChannel.class);
			b.childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				// 当新连接accept的时候，这个方法会调用
				public void initChannel(SocketChannel ch) throws Exception {
					ChannelPipeline pipeline = ch.pipeline();
					pipeline.addLast("logger", new LoggingHandler());
					pipeline.addLast("encoder", new JPbEncoder());
					pipeline.addLast("decoder", new JPbDecoder());
					pipeline.addLast("handler", handler);
				}
			});
			b.bind(port).sync().channel().closeFuture().sync();
		} catch (InterruptedException e) {
			logger.error("start server error", e);
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

	public JPbSocketNettyServer() {
	}
}
